//package com.example.demo.util;
//
//import javafx.util.Pair;
//import org.elasticsearch.action.search.SearchResponse;
//import org.elasticsearch.index.query.BoolQueryBuilder;
//import org.elasticsearch.index.query.MatchQueryBuilder;
//import org.elasticsearch.index.query.MultiMatchQueryBuilder;
//import org.elasticsearch.index.query.QueryBuilders;
//import org.elasticsearch.index.query.RangeQueryBuilder;
//import org.elasticsearch.index.query.TermQueryBuilder;
//import org.elasticsearch.index.query.TermsQueryBuilder;
//import org.elasticsearch.search.SearchHits;
//import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.data.domain.PageRequest;
//import org.springframework.data.domain.Pageable;
//import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
//import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
//import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
//import org.springframework.stereotype.Service;
//
//import javax.annotation.Resource;
//import java.util.ArrayList;
//import java.util.Collection;
//import java.util.List;
//import java.util.Map;
//
//@Service
//public abstract class EsSearchServiceImpl<T> implements EsSearchService<T> {
//    @Resource
//    ElasticsearchTemplate elasticsearchTemplate;
//
//    @Override
//    public boolean createIndex(Class<T> tClass) {
//        return elasticsearchTemplate.createIndex(tClass);
//    }
//
//    @Override
//    public boolean putMapping(Class<T> tClass) {
//        return elasticsearchTemplate.putMapping(tClass);
//    }
//
//
//    @Override
//    public boolean existIndex(Class<T> tClass) {
//        return elasticsearchTemplate.indexExists(tClass);
//    }
//
//    @Override
//    public boolean deleteIndex(Class<T> tClass) {
//        return elasticsearchTemplate.deleteIndex(tClass);
//    }
//
//    /**
//     * @param pageParam
//     * @param boTermQuery
//     * @param tClass
//     * @return
//     */
//    @Override
//    public List<T> queryList(PageParam pageParam, BoTermQuery boTermQuery, Class<T> tClass) {
//        Pageable pageable = PageRequest.of(pageParam.getPageNum(), pageParam.getPageSize());
//        BoolQueryBuilder queryBuilder = createQueryBuilder(boTermQuery);
//        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
//                .withQuery(queryBuilder)
//                .withPageable(pageable)
//                .build();
//        return elasticsearchTemplate.queryForPage(searchQuery, tClass).getContent();
//    }
//
//    @Override
//    public List<T> queryListHighlight(PageParam pageParam, BoTermQuery boTermQuery, List<String> highlightFields, String indexName, Class<T> tClass) {
//        BoolQueryBuilder queryBuilder = createQueryBuilder(boTermQuery);
//        HighlightBuilder highlightBuilder = createHighlightBuilder(highlightFields);
//        SearchResponse searchResponse = elasticsearchTemplate.getClient().prepareSearch(indexName)
//                .setQuery(queryBuilder)
//                .highlighter(highlightBuilder)
//                .setFrom(pageParam.getPageNum())
//                .setSize(pageParam.getPageSize())
//                .get();
//        SearchHits searchHits = searchResponse.getHits();
//        List<T> results = new ArrayList<>();
//        //组装结果
//        for (SearchHit searchHit : searchHits) {
//            Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
//            Map<String, HighlightField> highlightFieldsResult = searchHit.getHighlightFields();
//            try {
//                T t = tClass.newInstance();
//                Field[] declaredFields = t.getClass().getDeclaredFields();
//                for (Field field : declaredFields) {
//                    field.setAccessible(true);
//                    String name = field.getName();
//                    if (highlightFieldsResult.get(name) != null) {
//                        field.set(t, (highlightFieldsResult.get(name).getFragments()[0]).toString());
//                    } else {
//                        Object fieldValue = sourceAsMap.get(name);
//                        field.set(t, fieldValue);
//                    }
//                }
//                results.add(t);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//        return results;
//    }
//
//    /**
//     * 构造查询器
//     *
//     * @param boTermQuery
//     * @return
//     */
//    private BoolQueryBuilder createQueryBuilder(BoTermQuery boTermQuery) {
//        List<Pair<String, ?>> termConditions = boTermQuery.getTermConditions();
//        Map<String, Pair<?, ?>> rangeConditions = boTermQuery.getRangeConditions();
//        List<Pair<?, String>> matchConditions = boTermQuery.getMatchConditions();
//
//        BoTermQuery.Should should = boTermQuery.getShould();
//        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        if (should != null) {
//            boolQueryBuilder.minimumShouldMatch(should.getMinimumNumberShouldMatch());
//            //should条件
//            List<Pair<String, ?>> shouldTermConditions = should.getTermConditions();
//            List<Pair<?, String>> shouldMatchConditions = should.getMatchConditions();
//            Map<String, Pair<?, ?>> shouldRangeConditions = should.getRangeConditions();
//
//            if (shouldTermConditions.size() > 0) {
//                for (Pair<String, ?> shouldTermPair : shouldTermConditions) {
//                    if (shouldTermPair.getValue() instanceof Collection) {
//                        Collection<?> formatTermPair = (Collection<?>) shouldTermPair.getValue();
//                        TermsQueryBuilder termsShouldQueryBuilder = QueryBuilders.termsQuery(shouldTermPair.getKey(), formatTermPair);
//                        boolQueryBuilder.should(termsShouldQueryBuilder);
//                    } else {
//                        TermQueryBuilder termShouldQueryBuilder = QueryBuilders.termQuery(shouldTermPair.getKey(), shouldTermPair.getValue());
//                        boolQueryBuilder.should(termShouldQueryBuilder);
//                    }
//                }
//            }
//            //匹配
//            if (shouldMatchConditions.size() > 0) {
//                for (Pair<?, String> shouldMatchPair : shouldMatchConditions) {
//                    if (shouldMatchPair.getKey() instanceof String[]) {
//                        String[] formatPairKey = (String[]) shouldMatchPair.getKey();
//                        MultiMatchQueryBuilder multiShouldMatchQueryBuilder = QueryBuilders
//                                .multiMatchQuery(shouldMatchPair.getValue(), formatPairKey)
//                                .analyzer("ik_max_word");
//                        boolQueryBuilder.should(multiShouldMatchQueryBuilder);
//                    } else if (shouldMatchPair.getKey() instanceof String) {
//                        String formatPairKey = (String) shouldMatchPair.getKey();
//                        MatchQueryBuilder shouldMatchQueryBuilder = QueryBuilders
//                                .matchQuery(formatPairKey, shouldMatchPair.getValue())
//                                .analyzer("ik_max_word");
//                        boolQueryBuilder.should(shouldMatchQueryBuilder);
//                    }
//                }
//            }
//            //范围
//            if (shouldRangeConditions.size() > 0) {
//                for (Map.Entry<String, Pair<?, ?>> shouldRangeEntry : shouldRangeConditions.entrySet()) {
//                    RangeQueryBuilder rangeShouldQueryBuilder = QueryBuilders.rangeQuery(shouldRangeEntry.getKey());
//                    rangeShouldQueryBuilder.to(shouldRangeEntry.getValue().getValue()).from(shouldRangeEntry.getValue().getKey());
//                    boolQueryBuilder.should(rangeShouldQueryBuilder);
//                }
//            }
//        }
//        //过滤条件
//        if (termConditions.size() > 0) {
//            for (Pair<String, ?> termPair : termConditions) {
//                if (termPair.getValue() instanceof Collection) {
//                    Collection<?> formatTermPair = (Collection<?>) termPair.getValue();
//                    TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(termPair.getKey(), formatTermPair);
//                    boolQueryBuilder.filter(termsQueryBuilder);
//                } else {
//                    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(termPair.getKey(), termPair.getValue());
//                    boolQueryBuilder.filter(termQueryBuilder);
//                }
//            }
//        }
//        //匹配条件
//        if (matchConditions.size() > 0) {
//            for (Pair<?, String> matchPair : matchConditions) {
//                if (matchPair.getKey() instanceof String[]) {
//                    String[] formatPairKey = (String[]) matchPair.getKey();
//                    MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders
//                            .multiMatchQuery(matchPair.getValue(), formatPairKey)
//                            .analyzer("ik_max_word");
//                    boolQueryBuilder.filter(multiMatchQueryBuilder);
//                } else if (matchPair.getKey() instanceof String) {
//                    String formatPairKey = (String) matchPair.getKey();
//                    MatchQueryBuilder matchQueryBuilder = QueryBuilders
//                            .matchQuery(formatPairKey, matchPair.getValue())
//                            .analyzer("ik_max_word");
//                    boolQueryBuilder.filter(matchQueryBuilder);
//                }
//            }
//        }
//        //range条件
//        if (rangeConditions.size() > 0) {
//            for (Map.Entry<String, Pair<?, ?>> rangeEntry : rangeConditions.entrySet()) {
//                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(rangeEntry.getKey());
//                rangeQueryBuilder.to(rangeEntry.getValue().getValue()).from(rangeEntry.getValue().getKey());
//                boolQueryBuilder.filter(rangeQueryBuilder);
//            }
//        }
//        return boolQueryBuilder;
//    }
//
//    /**
//     * 构造高亮器
//     *
//     * @param fieldNames
//     * @return
//     */
//    private HighlightBuilder createHighlightBuilder(List<String> fieldNames) {
//        HighlightBuilder highlightBuilder = new HighlightBuilder()
//                .preTags("<span style='color:red'>")
//                .postTags("</span>");
//        //设置高亮字段
//        for (String fieldName : fieldNames) {
//            highlightBuilder.field(fieldName);
//        }
//        return highlightBuilder;
//    }
//}
